package com.ukefu.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.ByteBuffer;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.jasypt.util.text.BasicTextEncryptor;
import org.joda.time.Interval;
import org.joda.time.Period;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.web.multipart.MultipartFile;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.googlecode.aviator.AviatorEvaluator;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.Member;
import com.lmax.disruptor.dsl.Disruptor;
import com.ukefu.core.UKDataContext;
import com.ukefu.util.asr.AsrResult;
import com.ukefu.util.event.AiEvent;
import com.ukefu.util.event.MultiUpdateEvent;
import com.ukefu.util.event.UserDataEvent;
import com.ukefu.util.event.UserEvent;
import com.ukefu.util.mail.MailSender;
import com.ukefu.util.rpc.RPCDataBean;
import com.ukefu.util.sms.SmsService;
import com.ukefu.webim.service.cache.CacheHelper;
import com.ukefu.webim.service.repository.AdTypeRepository;
import com.ukefu.webim.service.repository.AiConfigRepository;
import com.ukefu.webim.service.repository.AreaTypeRepository;
import com.ukefu.webim.service.repository.AttachmentRepository;
import com.ukefu.webim.service.repository.CallOutNamesRepository;
import com.ukefu.webim.service.repository.CrmSchemeRepository;
import com.ukefu.webim.service.repository.PbxHostRepository;
import com.ukefu.webim.service.repository.QualityConfigRepository;
import com.ukefu.webim.service.repository.SMSTemplateRepository;
import com.ukefu.webim.service.repository.SecretRepository;
import com.ukefu.webim.service.repository.SmsResultRepository;
import com.ukefu.webim.service.repository.StatusEventHistoryRepository;
import com.ukefu.webim.service.repository.StatusEventRepository;
import com.ukefu.webim.service.repository.SystemConfigRepository;
import com.ukefu.webim.service.repository.SystemMessageRepository;
import com.ukefu.webim.service.repository.TablePropertiesRepository;
import com.ukefu.webim.service.repository.TemplateRepository;
import com.ukefu.webim.service.repository.WorkserviceTimeRepository;
import com.ukefu.webim.util.CallCenterUtils;
import com.ukefu.webim.util.HttpClientUtil;
import com.ukefu.webim.util.OnlineUserUtils;
import com.ukefu.webim.util.server.message.SessionConfigItem;
import com.ukefu.webim.web.model.AdType;
import com.ukefu.webim.web.model.AiConfig;
import com.ukefu.webim.web.model.AttachmentFile;
import com.ukefu.webim.web.model.CallOutNames;
import com.ukefu.webim.web.model.CrmScheme;
import com.ukefu.webim.web.model.JobDetail;
import com.ukefu.webim.web.model.JobTask;
import com.ukefu.webim.web.model.PbxHost;
import com.ukefu.webim.web.model.QualityConfig;
import com.ukefu.webim.web.model.SNSAccount;
import com.ukefu.webim.web.model.Secret;
import com.ukefu.webim.web.model.SessionConfig;
import com.ukefu.webim.web.model.SmsResult;
import com.ukefu.webim.web.model.SmsTemplate;
import com.ukefu.webim.web.model.StatusEvent;
import com.ukefu.webim.web.model.StatusEventHistory;
import com.ukefu.webim.web.model.SysDic;
import com.ukefu.webim.web.model.SystemConfig;
import com.ukefu.webim.web.model.SystemMessage;
import com.ukefu.webim.web.model.TableProperties;
import com.ukefu.webim.web.model.Template;
import com.ukefu.webim.web.model.UKeFuDic;
import com.ukefu.webim.web.model.User;
import com.ukefu.webim.web.model.VoiceTranscription;
import com.ukefu.webim.web.model.WorkOrders;
import com.ukefu.webim.web.model.WorkSession;
import com.ukefu.webim.web.model.WorkserviceTime;

import eu.bitwalker.useragentutils.UserAgent;
import freemarker.template.Configuration;
import freemarker.template.TemplateException;
import io.netty.handler.codec.http.HttpHeaders;
import net.coobird.thumbnailator.Thumbnails;


public class UKTools {
	private static MD5 md5 = new MD5();
	
	public static SimpleDateFormat dateFormate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;
	
	public static SimpleDateFormat callCenterDateFormate = new SimpleDateFormat("yyyyMMdd_HHmmss") ;
	
	public static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd") ;
	
	public static SimpleDateFormat simpleDateFormat2= new SimpleDateFormat("yyyyMMddHHmmss") ;
	
	public static SimpleDateFormat timeRangeDateFormat = new SimpleDateFormat("HH:mm");
	
	public static final Pattern INSECURE_URI = Pattern.compile("[\\s\\S]*?(\\.\\.)[\\s\\S]*?");
	
	public static final  DecimalFormat defaultNumberFormt = new DecimalFormat("00") ;
	
	static{
		dateFormate.setLenient(true);
		simpleDateFormat.setLenient(true);
	}
	/**
	 * 当前时间+已过随机生成的 长整形数字
	 * @return
	 */
	public static String genID(){
		return Base62.encode(getUUID()).toLowerCase() ;
	}
	
	public static String genIDByKey(String key){
		return Base62.encode(key).toLowerCase() ;
	}
	
	public static String getUUID(){
		return UUID.randomUUID().toString().replace("-", "") ;
	}
	
	public static String getContextID(String session){
		return session.replaceAll("-", "") ;
	}
	
	public static synchronized String md5(String str) {
		return md5.getMD5ofStr(md5.getMD5ofStr(str));
	}
	
	public static String md5(byte[] bytes) {
		return md5.getMD5ofByte(bytes);
	}
	
	public static void copyProperties(Object source, Object target,String... ignoreProperties)  
	        throws BeansException {  
	  
	    Assert.notNull(source, "Source must not be null");  
	    Assert.notNull(target, "Target must not be null");  
	  
	    Class<?> actualEditable = target.getClass();  
	    PropertyDescriptor[] targetPds = BeanUtils.getPropertyDescriptors(actualEditable);  
	    List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null;  
	  
	    for (PropertyDescriptor targetPd : targetPds) {  
	        Method writeMethod = targetPd.getWriteMethod();  
	        if (writeMethod != null && (ignoreProperties == null || (!ignoreList.contains(targetPd.getName())))) {  
	            PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(source.getClass(), targetPd.getName());  
	            if (sourcePd != null && !targetPd.getName().equalsIgnoreCase("id")) {  
	                Method readMethod = sourcePd.getReadMethod();  
	                if (readMethod != null &&  
	                        ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {  
	                    try {  
	                        if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {  
	                            readMethod.setAccessible(true);  
	                        }  
	                        Object value = readMethod.invoke(source);  
	                        if(value != null){  //只拷贝不为null的属性 by zhao  
	                            if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {  
	                                writeMethod.setAccessible(true);  
	                            }  
	                            writeMethod.invoke(target, value);  
	                        }  
	                    }  
	                    catch (Throwable ex) {  
	                        throw new FatalBeanException(  
	                                "Could not copy property '" + targetPd.getName() + "' from source to target", ex);  
	                    }  
	                }  
	            }  
	        }  
	    }  
	}  
	
	public static long ipToLong(String ipAddress) {
		long result = 0;
		String[] ipAddressInArray = ipAddress.split("\\.");
		if(ipAddressInArray!=null && ipAddressInArray.length == 4){
			for (int i = 3; i >= 0; i--) {
				long ip = Long.parseLong(ipAddressInArray[3 - i]);
	
				// left shifting 24,16,8,0 and bitwise OR
	
				// 1. 192 << 24
				// 1. 168 << 16
				// 1. 1 << 8
				// 1. 2 << 0
				result |= ip << (i * 8);
	
			}
		}
		return result;
	}

	public static String longToIp2(long ip) {

		return ((ip >> 24) & 0xFF) + "." + ((ip >> 16) & 0xFF) + "."
				+ ((ip >> 8) & 0xFF) + "." + (ip & 0xFF);
	}
	/***
	 * ID编码 ， 发送对话的时候使用
	 * @param id
	 * @param nid
	 * @return
	 */
	public static String genNewID(String id , String nid){
		StringBuffer strb = new StringBuffer();
		if(id!=null && nid!=null){
			int length = Math.max(id.length(), nid.length()); 
			for(int i=0 ; i<length ; i++){
				if(nid.length() > i && id.length() > i){
					int cur = (id.charAt(i) + nid.charAt(i)) / 2 ;
					strb.append((char)cur) ;
				}else if(nid.length() > i){
					strb.append(nid.charAt(i)) ;
				}else{
					strb.append(id.charAt(i)) ;
				}
			}
		}
		return strb.toString() ;
	}
	
	public static void published(UserEvent event){
		@SuppressWarnings("unchecked")
		Disruptor<UserDataEvent> disruptor = (Disruptor<UserDataEvent>) UKDataContext.getContext().getBean("disruptor") ;
		long seq = disruptor.getRingBuffer().next();
		disruptor.getRingBuffer().get(seq).setEvent(event); ;
		disruptor.getRingBuffer().publish(seq);
	}
	/**
	 * 
	 * @param request
	 * @return
	 */
	public static Map<String,Object> getRequestParam(HttpServletRequest request){
		Map<String,Object> values = new HashMap<String,Object>();
		Enumeration<String> enums = request.getParameterNames() ;
		while(enums.hasMoreElements()){
			String param = enums.nextElement() ;
			values.put(param,request.getParameter(param)) ;
		}
		return values;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static void multiupdate(MultiUpdateEvent event){
		Disruptor<UserDataEvent> disruptor = (Disruptor<UserDataEvent>) UKDataContext.getContext().getBean("multiupdate") ;
		long seq = disruptor.getRingBuffer().next();
		disruptor.getRingBuffer().get(seq).setEvent(event); 
		disruptor.getRingBuffer().publish(seq);
	}
	
	@SuppressWarnings({ "unchecked"})
	public static void ai(UserEvent event){
		Disruptor<AiEvent> disruptor = (Disruptor<AiEvent>) UKDataContext.getContext().getBean("ai") ;
		long seq = disruptor.getRingBuffer().next();
		disruptor.getRingBuffer().get(seq).setEvent(event); ;
		disruptor.getRingBuffer().publish(seq);
	}
	/**
	 * 
	 * @param request
	 * @return
	 */
	public static String getParameter(HttpServletRequest request){
		Enumeration<String> names = request.getParameterNames() ;
		StringBuffer strb = new StringBuffer();
		while(names.hasMoreElements()){
			String name = names.nextElement() ;
			if(name.indexOf("password") < 0){	//不记录 任何包含 password 的参数内容
				if(strb.length() > 0){
					strb.append(",") ;
				}
				strb.append(name).append("=").append(request.getParameter(name)) ;
			}
		}
		return strb.toString() ;
		
	}
	
	/**
	 * 获取一天的开始时间
	 * @return
	 */
	public static Date getStartTime(){
		Calendar todayStart = Calendar.getInstance();  
        todayStart.set(Calendar.HOUR_OF_DAY, 0);  
        todayStart.set(Calendar.MINUTE, 0);  
        todayStart.set(Calendar.SECOND, 0);  
        todayStart.set(Calendar.MILLISECOND, 0);  
        return todayStart.getTime();  
	}
	
	/**
	 * 获取一天的开始时间
	 * @return
	 */
	public static Date getWeekStartTime(){
		Calendar weekStart = Calendar.getInstance();  
		weekStart.set(weekStart.get(Calendar.YEAR), weekStart.get(Calendar.MONDAY), weekStart.get(Calendar.DAY_OF_MONTH), 0, 0, 0);  
		weekStart.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); 
        return weekStart.getTime();  
	}
	
	/**
	 * 获取一天的开始时间
	 * @return
	 */
	public static Date getLast30Day(){
		Calendar todayStart = Calendar.getInstance();  
		todayStart.set(Calendar.DAY_OF_MONTH, todayStart.get(Calendar.DAY_OF_MONTH) - 30);
		todayStart.set(Calendar.HOUR_OF_DAY, 0);  
        todayStart.set(Calendar.MINUTE, 0);  
        todayStart.set(Calendar.SECOND, 0);  
        todayStart.set(Calendar.MILLISECOND, 0);  
        return todayStart.getTime();  
	}
	
	public static synchronized String localMd5(String str) {
		return md5.getMD5ofStr(str) ;
	}
	
	/**
	 * 获取一天的开始时间
	 * @return
	 */
	public static Date getLastDay(int days){
		Calendar todayStart = Calendar.getInstance();  
		todayStart.set(Calendar.DAY_OF_MONTH, todayStart.get(Calendar.DAY_OF_MONTH) - days);
		todayStart.set(Calendar.HOUR_OF_DAY, 0);  
        todayStart.set(Calendar.MINUTE, 0);  
        todayStart.set(Calendar.SECOND, 0);  
        todayStart.set(Calendar.MILLISECOND, 0);  
        return todayStart.getTime();  
	}
	
	/**
	 * 获取指定日期前多少天的开始时间
	 * @return
	 */
	public static Date getLastDay(Date date ,int days){
		Calendar todayStart = Calendar.getInstance();  
		todayStart.setTime(date);
		todayStart.set(Calendar.DAY_OF_MONTH, todayStart.get(Calendar.DAY_OF_MONTH) - days);
		todayStart.set(Calendar.HOUR_OF_DAY, 0);  
		todayStart.set(Calendar.MINUTE, 0);  
		todayStart.set(Calendar.SECOND, 0);  
		todayStart.set(Calendar.MILLISECOND, 0);  
		return todayStart.getTime();  
	}
	
	/**
	 * 	获取指定日期后几天的开始时间
	 * @param date
	 * @param days
	 * @return
	 */
	public static Date getNextDay(Date date ,int days){
		Calendar todayStart = Calendar.getInstance();  
		todayStart.setTime(date);
		todayStart.set(Calendar.DAY_OF_MONTH, todayStart.get(Calendar.DAY_OF_MONTH) + days);
		todayStart.set(Calendar.HOUR_OF_DAY, 0);  
		todayStart.set(Calendar.MINUTE, 0);  
		todayStart.set(Calendar.SECOND, 0);  
		todayStart.set(Calendar.MILLISECOND, 0);  
		return todayStart.getTime();  
	}
	
	/**
	 * 获取一天的结束时间
	 * @return
	 */
	public static Date getEndTime(){
		Calendar todayEnd = Calendar.getInstance();  
        todayEnd.set(Calendar.HOUR_OF_DAY, 23);  
        todayEnd.set(Calendar.MINUTE, 59);  
        todayEnd.set(Calendar.SECOND, 59);  
        todayEnd.set(Calendar.MILLISECOND, 999);  
        return todayEnd.getTime();  
	}
	
	/**
	 * 获取一天的结束时间
	 * @return
	 */
	public static Date getLastTime(int secs){
		Calendar todayEnd = Calendar.getInstance();
        todayEnd.add(Calendar.SECOND, secs*-1);  
        return todayEnd.getTime();  
	}
	
	public static void noCacheResponse(HttpServletResponse response){
		response.setDateHeader("Expires",0);
        response.setHeader("Buffer","True");
        response.setHeader("Cache-Control","no-cache");
        response.setHeader("Cache-Control","no-store");
        response.setHeader("Expires","0");
        response.setHeader("ETag",String.valueOf(System.currentTimeMillis()));
        response.setHeader("Pragma","no-cache");
        response.setHeader("Date",String.valueOf(new Date()));
        response.setHeader("Last-Modified",String.valueOf(new Date()));
	}
	
	public static BrowserClient parseClient(HttpServletRequest request){
		BrowserClient client = new BrowserClient() ;
		String  browserDetails  =   request.getHeader("User-Agent");
        UserAgent parse = UserAgent.parseUserAgentString(browserDetails) ;
        client.setUseragent(browserDetails);
        if(parse!=null) {
        	if(parse.getOperatingSystem()!=null) {
        		client.setOs(processOs(parse.getOperatingSystem().getName()));
        	}
        	if(parse.getBrowser()!=null) {
        		client.setBrowser(processBrowser(parse.getBrowser().getName()));
        	}
        	if(parse.getBrowser().getVersion(browserDetails)!=null) {
        		client.setVersion(parse.getBrowser().getVersion(browserDetails).getVersion());
        	}
        }
        return client ;
	}
	/**
	 * 
	 * @param osname
	 * @return
	 */
	public static String processOs(String osname) {
		String group = null ;
		if(!StringUtils.isBlank(osname) && osname.toLowerCase().indexOf("windows")>=0) {
			group = "Windows" ;
		}else if(!StringUtils.isBlank(osname) && osname.toLowerCase().indexOf("android")>=0) {
			group = "Android" ;
		}else if(!StringUtils.isBlank(osname) && osname.toLowerCase().indexOf("ios")>=0) {
			group = "IOS" ;
		}else if(!StringUtils.isBlank(osname) && osname.toLowerCase().indexOf("linux")>=0) {
			group = "Linux" ;
		}else if(!StringUtils.isBlank(osname) && osname.toLowerCase().indexOf("mac os")>=0) {
			group = "Mac OS" ;
		}else {
			group = osname ;
		}
		return group ;
	}
	/**
	 * 
	 * @param browser
	 * @return
	 */
	public static String processBrowser(String browser) {
		String group = null ;
		if(!StringUtils.isBlank(browser) && browser.toLowerCase().indexOf("firefox")>=0) {
			group = "Firefox" ;
		}else if(!StringUtils.isBlank(browser) && browser.toLowerCase().indexOf("chrome")>=0) {
			group = "Chrome" ;
		}else if(!StringUtils.isBlank(browser) && browser.toLowerCase().indexOf("internet explorer")>=0) {
			group = "IE" ;
		}else if(!StringUtils.isBlank(browser) && browser.toLowerCase().indexOf("edge")>=0) {
			group = "Edge" ;
		}else if(!StringUtils.isBlank(browser) && browser.toLowerCase().indexOf("sofari")>=0) {
			group = "Sofari" ;
		}else {
			group = browser ;
		}
		return group ;
	}
	/**
	 * 活动JPA统计结果
	 * @param values
	 * @return
	 */
	public static WebIMReport getWebIMReport(List<Object> values){
		WebIMReport report = new WebIMReport();
		if(values!=null && values.size()>0){
			Object[] value = (Object[]) values.get(0) ;
			if(value.length>=2){
				report.setIpnums((long) value[0]);
				report.setPvnums((long) value[1]);
			}
		}
		return report ;
	}
	
	/**
	 * 活动JPA统计结果
	 * @param values
	 * @return
	 */
	public static WebIMReport getWebIMInviteStatus(List<Object> values){
		WebIMReport report = new WebIMReport();
		if(values!=null && values.size()>0){
			
			for(int i= 0 ; i<values.size() ; i++){
				Object[] value = (Object[]) values.get(i) ;
				if(value.length>=2){
					String invitestatus = (String) value[0] ;
					if(UKDataContext.OnlineUserInviteStatus.DEFAULT.toString().equals(invitestatus) || invitestatus == null){
						report.setUsers((long) value[1]);
					}else if(UKDataContext.OnlineUserInviteStatus.INVITE.toString().equals(invitestatus)){
						report.setInviteusers((long) value[1]);
					}else if(UKDataContext.OnlineUserInviteStatus.REFUSE.toString().equals(invitestatus)){
						report.setRefuseusers((long) value[1]);
					}
				}
			}
		}
		return report ;
	}
	
	/**
	 * 活动JPA统计结果
	 * @param values
	 * @return
	 */
	public static List<WebIMReport> getWebIMInviteAgg(List<Object> values){
		List<WebIMReport> webIMReportList = new ArrayList<WebIMReport>() ;
		if(values!=null && values.size()>0){
			for(int i= 0 ; i<values.size() ; i++){
				Object[] value = (Object[]) values.get(i) ;
				WebIMReport report = new WebIMReport();
				if(value.length==3){
					report.setData((String) value[0]);
					report.setIpnums((long) value[1]);
					report.setPvnums((long) value[2]);
				}
				webIMReportList.add(report) ;
			}
		}
		return webIMReportList ;
	}
	
	/**
	 * 活动JPA统计结果
	 * @param values
	 * @return
	 */
	public static List<WebIMReport> getWebIMDataAgg(List<Object> values){
		List<WebIMReport> webIMReportList = new ArrayList<WebIMReport>() ;
		if(values!=null && values.size()>0){
			for(int i= 0 ; i<values.size() ; i++){
				Object[] value = (Object[]) values.get(i) ;
				WebIMReport report = new WebIMReport();
				if(value.length==2){
					if(value[0] == null || value[0].toString().equalsIgnoreCase("null")||StringUtils.isBlank(value[0].toString())){
						report.setData("未知");
					}else{
						report.setData((String) value[0]);
					}
					report.setUsers((long) value[1]);
				}
				webIMReportList.add(report) ;
			}
		}
		return webIMReportList ;
	}
	
	/**
	 * 活动JPA统计结果
	 * @param values
	 * @return
	 */
	public static WebIMReport getWebIMInviteResult(List<Object> values){
		WebIMReport report = new WebIMReport();
		if(values!=null && values.size()>0){
			
			for(int i= 0 ; i<values.size() ; i++){
				Object[] value = (Object[]) values.get(i) ;
				if(value.length>=2){
					String invitestatus = (String) value[0] ;
					if(UKDataContext.OnlineUserInviteStatus.DEFAULT.toString().equals(invitestatus) || invitestatus == null){
						report.setUsers((long) value[1]);
					}else if(UKDataContext.OnlineUserInviteStatus.ACCEPT.toString().equals(invitestatus)){
						report.setInviteusers((long) value[1]);
					}else if(UKDataContext.OnlineUserInviteStatus.REFUSE.toString().equals(invitestatus)){
						report.setRefuseusers((long) value[1]);
					}
				}
			}
		}
		return report ;
	}
	
	/**
	 * 活动JPA统计结果
	 * @param values
	 * @return
	 */
	public static WeiXinReport getWeiXinReportResult(List<Object> values){
		WeiXinReport report = new WeiXinReport();
		if(values!=null && values.size()>0){
			for(int i= 0 ; i<values.size() ; i++){
				Object[] value = (Object[]) values.get(i) ;
				if(value.length>=2){
					String event = (String) value[0] ;
					if(UKDataContext.WeiXinEventTypeEnum.SUB.toString().equals(event)){
						report.setSubs((long) value[1]);
					}else if(UKDataContext.WeiXinEventTypeEnum.UNSUB.toString().equals(event)){
						report.setUnsubs((long) value[1]);
					}
				}
			}
		}
		return report ;
	}
	
	public static Map<String, Object> transBean2Map(Object obj) {  
		  
        if(obj == null){  
            return null;  
        }          
        Map<String, Object> map = new HashMap<String, Object>();  
        try {  
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());  
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  
            for (PropertyDescriptor property : propertyDescriptors) {  
                String key = property.getName();  
  
                // 过滤class属性  
                if (!key.equals("class")) {  
                    // 得到property对应的getter方法 
                	
                    Method readMethod = property.getReadMethod(); 
                    
                    if (readMethod != null) {  
                    	Object value = readMethod.invoke(obj);  
                    	if(value instanceof Date){
                    		value = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) value) ;
                    	}
	                    map.put(key, value);
	                }  
                }  
            }  
        } catch (Exception e) {  
            System.out.println("transBean2Map Error " + e);  
        }  
  
        return map;  
  
    }
	
	public static void populate(Object bean , Map<Object , Object> properties) throws IllegalAccessException, InvocationTargetException{
		ConvertUtils.register(new Converter()    
		{    
			@SuppressWarnings("rawtypes")    
			@Override    
			public Object convert(Class arg0, Object arg1)    
			{    
				if(arg1 == null)    
				{    
					return null;    
				}    
				if(arg1 instanceof Date){
					return arg1 ;
				}else if(!(arg1 instanceof String)){    
					throw new ConversionException("只支持字符串转换 !");    
				}    
				String str = (String)arg1;    
				if(str.trim().equals(""))    
				{    
					return null;    
				}    

				SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    

				try{    
					return sd.parse(str);    
				} catch(Exception e)    
				{    
					throw new RuntimeException(e);    
				}    

			}    

		}, java.util.Date.class);  
		if (properties == null || bean == null) {    
			return;    
		}    
		try {    
			BeanUtilsBean.getInstance().populate(bean, properties);
		} catch (Exception e) {
			e.printStackTrace();
		}    
	}
	
	public static byte[] toBytes(Object object) throws Exception {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ObjectOutputStream objectOutput = new ObjectOutputStream(out);
		objectOutput.writeObject(object);
		return out.toByteArray();
	}

	public static Object toObject(byte[] data) throws Exception {
		ByteArrayInputStream input = new ByteArrayInputStream(data);
		ObjectInputStream objectInput = new ObjectInputStream(input);
		return objectInput.readObject();
	}
	
	/**
     * 
     * @param str
     * @return
     * @throws NoSuchAlgorithmException 
     */
    public static String encryption(String str) throws NoSuchAlgorithmException{
    	BasicTextEncryptor  textEncryptor = new BasicTextEncryptor ();
    	textEncryptor.setPassword(UKDataContext.getSystemSecrityPassword());
    	return textEncryptor.encrypt(str);
    }
    
    /**
     * 
     * @param str
     * @return
     * @throws NoSuchAlgorithmException 
     */
    public static String decryption(String str) throws NoSuchAlgorithmException{
    	BasicTextEncryptor  textEncryptor = new BasicTextEncryptor ();
    	textEncryptor.setPassword(UKDataContext.getSystemSecrityPassword());
    	return textEncryptor.decrypt(str);
    }
    
    public static String getTopic(String snsid ,String msgtype , String eventype , String eventkey , String msg){
    	StringBuffer strb = new StringBuffer() ;
		strb.append(snsid) ;
		strb.append(".").append(msgtype) ;
		if(msgtype.equals("text")){
			strb.append(".").append(msg) ;
		}else if(msgtype.equals("event")){
			strb.append(".").append(eventype.toLowerCase()) ;
			if(!StringUtils.isBlank(eventkey)){
				strb.append(".").append(eventkey) ;
			}
		}else{
			strb.append(".").append(msgtype) ;
		}
		return strb.toString() ;
    }
    
    public static String getTopic(String snsid ,String msgtype , String eventype){
    	StringBuffer strb = new StringBuffer() ;
		strb.append(snsid) ;
		strb.append(".").append(msgtype) ;
		if(msgtype.equals("text")){
			strb.append(".").append(msgtype) ;
		}else if(msgtype.equals("event")){
			strb.append(".").append(eventype.toLowerCase()) ;
		}else{
			strb.append(".").append(msgtype) ;
		}
		return strb.toString() ;
    }
	/**
	 * 处理 对话消息中的图片
	 * @param message
	 * @return
	 */
    public static String filterChatMessage(String message){
    	Document document = Jsoup.parse(message) ;
    	Elements pngs = document.select("img[src]");
    	for (Element element : pngs) {
    		String imgUrl = element.attr("src");
    		if(imgUrl.indexOf("/res/image") >= 0){
    			element.attr("class", "ukefu-media-image") ;
    		}
    	}
    	return document.html() ;
    }
    public static int dayForWeek(){  
    	 Calendar c = Calendar.getInstance();  
    	 int dayForWeek = 0;  
    	 if(c.get(Calendar.DAY_OF_WEEK) == 1){  
    	  dayForWeek = 7;  
    	 }else{  
    	  dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;  
    	 }  
    	 return dayForWeek;   
    }  
    /**
     * 检查当前时间是否是在 时间范围内 ，时间范围的格式为 ： 08:30~11:30,13:30~17:30
     * @param timeRanges
     * @return
     * @throws Throwable 
     */
    public static boolean isInWorkingHours(SessionConfig sessionConfig,String apply){
    	List<SessionConfigItem> configItem = sessionConfig.getConfig() ;
    	boolean workintTime = false ;
    	boolean workType = false ;
    	String timeStr = timeRangeDateFormat.format(new Date()) , dayStr = simpleDateFormat.format(new Date());
    	//dayForWeek(dayStr);
    	if(configItem!=null && configItem.size() >0){		//设置了 工作时间段
    		WorkserviceTimeRepository workServiceTimeRes = UKDataContext.getContext().getBean(WorkserviceTimeRepository.class) ;
    		List<WorkserviceTime> workServiceTimeList = workServiceTimeRes.findByOrgi(sessionConfig.getOrgi()) ;
    		for(SessionConfigItem item : configItem){//工作时间段
    			for(WorkserviceTime wst : workServiceTimeList){//工作日，节日，假日等日期，星期设置
    				
    				if(!StringUtils.isBlank(apply) && apply.equals(wst.getApply())){//判断适用场景是否对应（文字客服 webim/）
    					
    					//判断该记录的星期，是否包含今天（星期）
    					if(wst.getWeek() !=null && wst.getWeek().contains((String.valueOf(dayForWeek()))) == true){
    						
    						//判断两条记录的日期类型是否相同（工作日，节日，假日）
    						if(!StringUtils.isBlank(wst.getTimetype()) && !StringUtils.isBlank(item.getType()) && wst.getTimetype().equals(item.getType())){
    							
    							//判断该工作时间段记录，是否是"工作"
    							if(!StringUtils.isBlank(item.getWorktype()) && !"nowork".equals(item.getWorktype())){//工作日
    								
    								String[] timeGroup = item.getWorkinghours().split("~") ;
									if(timeGroup.length == 2){
										if(timeGroup[0].compareTo(timeGroup[1]) >= 0){
											if(timeStr.compareTo(timeGroup[0]) >= 0 || timeStr.compareTo(timeGroup[1]) <= 0){
												workintTime = true ;
											}
										}else{
											if(timeStr.compareTo(timeGroup[0]) >= 0 && timeStr.compareTo(timeGroup[1]) <= 0){
												workintTime = true ;
											}
										}
									}
    							}else{
    								workType = true ;
    								workintTime = false ;
    							}
    						}
    					
    					//判断该记录的日期，是否包含今天（日期）
    					}else if(!StringUtils.isBlank(wst.getScope()) && ("one".equals(wst.getScope()) && dayStr.equals(wst.getBegin())) 
    							|| ("more".equals(wst.getScope()) && dayStr.compareTo(wst.getBegin()) >=0&& dayStr.compareTo(wst.getEnd()) <= 0)){
    						
    						//判断两条记录的日期类型是否相同（工作日，节日，假日）
    						if(!StringUtils.isBlank(wst.getTimetype()) && !StringUtils.isBlank(item.getType()) && wst.getTimetype().equals(item.getType())){
    							
    							//判断该工作时间段记录，是否是"工作"
    							if(!StringUtils.isBlank(item.getWorktype()) && !"nowork".equals(item.getWorktype())){//工作日
    								
    								String[] timeGroup = item.getWorkinghours().split("~") ;
									if(timeGroup.length == 2){
										if(timeGroup[0].compareTo(timeGroup[1]) >= 0){
											if(timeStr.compareTo(timeGroup[0]) >= 0 || timeStr.compareTo(timeGroup[1]) <= 0){
												workintTime = true ;
											}
										}else{
											if(timeStr.compareTo(timeGroup[0]) >= 0 && timeStr.compareTo(timeGroup[1]) <= 0){
												workintTime = true ;
											}
										}
									}
    							}else{
    								workType = true ;
    								workintTime = false ;
    							}
    						}
    					}
    				}
				}
			}
    		if(workType == true){
    			workintTime = false ;
    		}
		}
    	return workintTime ;
    }
    
    /**
     * 检查当前时间是否是在 时间范围内 ，时间范围的格式为 ： 08:30~11:30,13:30~17:30
     * @param timeRanges
     * @return
     * @throws Throwable 
     */
    public static boolean isInWorkingHours(SNSAccount snsaccount,String apply){
    	List<SessionConfigItem> configItem = snsaccount.getConfig() ;
    	boolean workintTime = false ;
    	boolean workType = false ;
    	String timeStr = timeRangeDateFormat.format(new Date()) , dayStr = simpleDateFormat.format(new Date());
    	//dayForWeek(dayStr);
    	if(configItem!=null && configItem.size() >0){		//设置了 工作时间段
    		WorkserviceTimeRepository workServiceTimeRes = UKDataContext.getContext().getBean(WorkserviceTimeRepository.class) ;
    		List<WorkserviceTime> workServiceTimeList = workServiceTimeRes.findByOrgi(snsaccount.getOrgi()) ;
    		for(SessionConfigItem item : configItem){//工作时间段
    			for(WorkserviceTime wst : workServiceTimeList){//工作日，节日，假日等日期，星期设置
    				
    				if(!StringUtils.isBlank(apply) && apply.equals(wst.getApply())){//判断适用场景是否对应（文字客服 webim/）
    					
    					//判断该记录的星期，是否包含今天（星期）
    					if(wst.getWeek() !=null && wst.getWeek().contains((String.valueOf(dayForWeek()))) == true){
    						
    						//判断两条记录的日期类型是否相同（工作日，节日，假日）
    						if(!StringUtils.isBlank(wst.getTimetype()) && !StringUtils.isBlank(item.getType()) && wst.getTimetype().equals(item.getType())){
    							
    							//判断该工作时间段记录，是否是"工作"
    							if(!StringUtils.isBlank(item.getWorktype()) && !"nowork".equals(item.getWorktype())){//工作日
    								
    								String[] timeGroup = item.getWorkinghours().split("~") ;
									if(timeGroup.length == 2){
										if(timeGroup[0].compareTo(timeGroup[1]) >= 0){
											if(timeStr.compareTo(timeGroup[0]) >= 0 || timeStr.compareTo(timeGroup[1]) <= 0){
												workintTime = true ;
											}
										}else{
											if(timeStr.compareTo(timeGroup[0]) >= 0 && timeStr.compareTo(timeGroup[1]) <= 0){
												workintTime = true ;
											}
										}
									}
    							}else{
    								workType = true ;
    								workintTime = false ;
    							}
    						}
    					
    					//判断该记录的日期，是否包含今天（日期）
    					}else if(!StringUtils.isBlank(wst.getScope()) && ("one".equals(wst.getScope()) && dayStr.equals(wst.getBegin())) 
    							|| ("more".equals(wst.getScope()) && dayStr.compareTo(wst.getBegin()) >=0&& dayStr.compareTo(wst.getEnd()) <= 0)){
    						
    						//判断两条记录的日期类型是否相同（工作日，节日，假日）
    						if(!StringUtils.isBlank(wst.getTimetype()) && !StringUtils.isBlank(item.getType()) && wst.getTimetype().equals(item.getType())){
    							
    							//判断该工作时间段记录，是否是"工作"
    							if(!StringUtils.isBlank(item.getWorktype()) && !"nowork".equals(item.getWorktype())){//工作日
    								
    								String[] timeGroup = item.getWorkinghours().split("~") ;
									if(timeGroup.length == 2){
										if(timeGroup[0].compareTo(timeGroup[1]) >= 0){
											if(timeStr.compareTo(timeGroup[0]) >= 0 || timeStr.compareTo(timeGroup[1]) <= 0){
												workintTime = true ;
											}
										}else{
											if(timeStr.compareTo(timeGroup[0]) >= 0 && timeStr.compareTo(timeGroup[1]) <= 0){
												workintTime = true ;
											}
										}
									}
    							}else{
    								workType = true ;
    								workintTime = false ;
    							}
    						}
    					}
    				}
				}
			}
    		if(workType == true){
    			workintTime = false ;
    		}
		}
    	return workintTime ;
    }
    
    public static File processImage(File destFile,File imageFile) throws FileNotFoundException, IOException{
		if(imageFile != null && imageFile.exists()){
			Thumbnails.of(imageFile).width(460).keepAspectRatio(true).toFile(destFile);
		}
		return destFile ;
    }
    
    public static File scaleImage(File destFile,File imageFile, float quality) throws FileNotFoundException, IOException{
		if(imageFile != null && imageFile.exists()){
			Thumbnails.of(imageFile).scale(1f).outputQuality(quality).toFile(destFile);
		}
		return destFile ;
    }

	public static String processEmoti(String message) {
		Pattern pattern = Pattern.compile("\\[([\\d]*?)\\]");
		SystemConfig systemConfig = (SystemConfig) CacheHelper.getSystemCacheBean().getCacheObject("systemConfig", UKDataContext.SYSTEM_ORGI) ; 
	    Matcher matcher = pattern.matcher(message);
	    StringBuffer strb = new StringBuffer();
	    while(matcher.find()) {
	    	if(systemConfig!=null && !StringUtils.isBlank(systemConfig.getIconstr())) {
	    		matcher.appendReplacement(strb,"<img src='"+systemConfig.getIconstr()+"/im/js/kindeditor/plugins/emoticons/images/"+matcher.group(1)+".png'>");
	    	}else {
	    		matcher.appendReplacement(strb,"<img src='/im/js/kindeditor/plugins/emoticons/images/"+matcher.group(1)+".png'>");
	    	}
	    }
	    matcher.appendTail(strb) ;
	    if(strb.length() == 0){
	    	strb.append(message) ;
	    }
	    return strb.toString().replaceAll("[\\ud800\\udc00-\\udbff\\udfff\\ud800-\\udfff]", "[表情]") ;
	}
	
	public static String getIpAddr(HttpServletRequest request) {  
	    String ip = request.getHeader("x-forwarded-for");  
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = request.getHeader("X-Forwarded-For");  
	    } 
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = request.getHeader("Proxy-Client-IP");  
	    }  
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = request.getHeader("WL-Proxy-Client-IP");  
	    }  
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = request.getRemoteAddr();  
	    }  
	    return ip;  
	}
	
	public static String getIpAddr(HttpHeaders headers , String remoteAddr) {  
	    String ip = headers.get("x-forwarded-for"); 
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = headers.get("X-Forwarded-For");  
	    } 
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = headers.get("Proxy-Client-IP");  
	    }  
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = headers.get("WL-Proxy-Client-IP");  
	    }  
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = remoteAddr;  
	    }  
	    return ip;  
	}
	
	public static boolean secConfirm(SecretRepository secRes , String orgi , String confirm){
		/**
    	 * 先调用 IMServer 
    	 */
    	boolean execute = false ;
    	List<Secret> secretConfig = secRes.findByOrgi(orgi) ;
    	if(!StringUtils.isBlank(confirm)){
        	if(secretConfig!=null && secretConfig.size() > 0){
        		Secret secret = secretConfig.get( 0) ;
        		if(UKTools.md5(confirm).equals(secret.getPassword())){
        			execute = true ;
        		}
        	}
    	}else if(secretConfig.size() == 0){
    		execute = true ;
    	}
    	return execute ;
	}
	
	public static void  processAttachmentFile(MultipartFile[] files, AttachmentRepository attachementRes , String path,User user , String orgi, WorkOrders workOrders, HttpServletRequest request  , String dataid , String modelid) throws IOException{
    	if(files!=null && files.length > 0){
    		workOrders.setAnonymous(true);//变更用途为是否有 附件
    		//保存附件
    		for(MultipartFile file : files){
    			if(file.getSize() > 0){			//文件尺寸 限制 ？在 启动 配置中 设置 的最大值，其他地方不做限制
    				String fileid = UKTools.md5(file.getBytes()) ;	//使用 文件的 MD5作为 ID，避免重复上传大文件
    				if(!StringUtils.isBlank(fileid)){
		    			AttachmentFile attachmentFile = new AttachmentFile() ;
		    			attachmentFile.setCreater(user.getId());
		    			attachmentFile.setOrgi(orgi);
		    			attachmentFile.setOrgan(user.getOrgan());
		    			attachmentFile.setDataid(dataid);
		    			attachmentFile.setModelid(modelid);
		    			attachmentFile.setModel(UKDataContext.ModelType.WORKORDERS.toString());
		    			attachmentFile.setFilelength((int) file.getSize());
		    			if(file.getContentType()!=null && file.getContentType().length() > 255){
		    				attachmentFile.setFiletype(file.getContentType().substring(0 , 255));
		    			}else{
		    				attachmentFile.setFiletype(file.getContentType());
		    			}
		    			if(file.getOriginalFilename()!=null && file.getOriginalFilename().length() > 255){
		    				attachmentFile.setTitle(file.getOriginalFilename().substring(0 , 255));
		    			}else{
		    				attachmentFile.setTitle(file.getOriginalFilename());
		    			}
		    			if(!StringUtils.isBlank(attachmentFile.getFiletype()) && attachmentFile.getFiletype().indexOf("image") >= 0){
		    				attachmentFile.setImage(true);
		    			}
		    			attachmentFile.setFileid(fileid);
		    			attachementRes.save(attachmentFile) ;
		    			FileUtils.writeByteArrayToFile(new File(path , "app/workorders/"+fileid), file.getBytes());
    				}
    			}
    		}
    		
    	}
    }
	/**
	 * 获取系统配置
	 * @return
	 */
	public static SystemConfig getSystemConfig(){
		SystemConfig systemConfig = (SystemConfig) CacheHelper.getSystemCacheBean().getCacheObject("systemConfig", UKDataContext.SYSTEM_ORGI) ;
		if(systemConfig == null){
			SystemConfigRepository systemConfigRes = UKDataContext.getContext().getBean(SystemConfigRepository.class) ;
			List<SystemConfig> configList = systemConfigRes.findByOrgi(UKDataContext.SYSTEM_ORGI) ;
	    	if(configList != null && configList.size() > 0){
	    		systemConfig = configList.get(0) ;
	    	}else {
	    		systemConfig = new SystemConfig();
	    		systemConfig.setOrgi(UKDataContext.SYSTEM_ORGI);
			}
		}
		return systemConfig;
	}
	
	/**
	 * 初始化呼叫中心功能里需要隐藏号码的字段
	 * @param tpRes
	 */
	public static void initSystemSecField(TablePropertiesRepository tpRes) {
		if(tpRes!= null) {
			List<TableProperties> tpList = tpRes.findBySecfield(true) ;
			CacheHelper.getSystemCacheBean().put(UKDataContext.UKEFU_SYSTEM_SECFIELD, tpList, UKDataContext.SYSTEM_ORGI) ;
		}
	}
	/**
	 * 获取系统地区配置
	 * @return
	 */
	public static void initSystemArea(){
		CacheHelper.getSystemCacheBean().delete(UKDataContext.UKEFU_SYSTEM_AREA, UKDataContext.SYSTEM_ORGI) ;
		AreaTypeRepository areaTypeRes = UKDataContext.getContext().getBean(AreaTypeRepository.class) ;
    	CacheHelper.getSystemCacheBean().put(UKDataContext.UKEFU_SYSTEM_AREA, areaTypeRes.findAll(), UKDataContext.SYSTEM_ORGI);
	}
	/**
	 * 缓存 广告位
	 * @return
	 */
	public static void initAdv(String orgi){
		CacheHelper.getSystemCacheBean().delete(UKDataContext.UKEFU_SYSTEM_ADV+"_"+orgi, orgi) ;
		AdTypeRepository adRes = UKDataContext.getContext().getBean(AdTypeRepository.class) ;
    	CacheHelper.getSystemCacheBean().put(UKDataContext.UKEFU_SYSTEM_ADV+"_"+orgi, adRes.findByOrgi(orgi),orgi);
	}
	
	public static Template getTemplate(String id){
		Template templet = null ;
		if((templet = (Template) CacheHelper.getSystemCacheBean().getCacheObject(id,  UKDataContext.SYSTEM_ORGI)) == null) {
			TemplateRepository templateRes = UKDataContext.getContext().getBean(TemplateRepository.class) ;
			//templet = templateRes.findByIdAndOrgi(id, UKDataContext.SYSTEM_ORGI);
			templet = templateRes.findById(id);
			CacheHelper.getSystemCacheBean().put(id, templet, UKDataContext.SYSTEM_ORGI);
		}
		return templet;
	}
	/**
	 * 
	 * @param id
	 * @param orgi
	 * @return
	 */
	public static SmsTemplate getSmsTemplate(String id , String orgi){
		return UKDataContext.getContext().getBean(SMSTemplateRepository.class).findByIdAndOrgi(id, orgi) ;
	}
	/**
	 * 按照权重获取广告
	 * @param adpos
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static AdType getPointAdv(String adpos,String orgi){
		List<AdType> adTypeList = new ArrayList<AdType>();
		List <AdType> cacheAdTypeList = (List<AdType>) CacheHelper.getSystemCacheBean().getCacheObject(UKDataContext.UKEFU_SYSTEM_ADV+"_"+orgi,orgi);
		if(cacheAdTypeList == null) {
			AdTypeRepository adRes = UKDataContext.getContext().getBean(AdTypeRepository.class) ;
			cacheAdTypeList = adRes.findByOrgi(orgi);
	    	CacheHelper.getSystemCacheBean().put(UKDataContext.UKEFU_SYSTEM_ADV+"_"+orgi,cacheAdTypeList,orgi);
		}
		List<SysDic> sysDicList = UKeFuDic.getInstance().getDic(UKDataContext.UKEFU_SYSTEM_ADPOS_DIC) ;
		SysDic sysDic = null ;
		if(sysDicList!=null){
			for(SysDic dic : sysDicList){
				if(dic.getCode().equals(adpos)){
					sysDic = dic ; break ;
				}
			}
		}
		if(adTypeList!=null && sysDic!=null){
			for(AdType adType : cacheAdTypeList){
				if(adType.getAdpos().equals(sysDic.getId())){
					adTypeList.add(adType) ;
				}
			}
		}
		return weitht(adTypeList) ;
	}
	private static Random random = new Random();   
	/**
	 * 
	 * 按照权重，获取广告内容
	 * @param adList
	 * @return
	 */
	private static AdType weitht(List<AdType> adList){
		AdType adType = null;
		int weight = 0 ;
		if(adList!=null && adList.size() > 0){
			for (AdType ad : adList) {    
	            weight += ad.getWeight() ;
	        }
			int n = random.nextInt(weight)  , m = 0 ;
			for (AdType ad : adList) {    
				if (m <= n && n < m + ad.getWeight()) {   
					adType = ad ; break; 
				}
				m += ad.getWeight();    
	        }
		}
		return adType ;
	}
	
	/** 
     * 16进制字符串转换为字符串 
     *  
     * @param s 
     * @return 
     */  
	public static String string2HexString(String strPart) {  
        StringBuffer hexString = new StringBuffer();  
        for (int i = 0; i < strPart.length(); i++) {  
            int ch = (int) strPart.charAt(i);  
            String strHex = Integer.toHexString(ch);  
            hexString.append(strHex);  
        }  
        return hexString.toString();  
    }
	
	/**
     * 
     * @param templetid
     * @throws IOException 
     * @throws TemplateException 
     */
    @SuppressWarnings("deprecation")
	public static String getTemplet(String templet , Map<String , Object> values) throws IOException, TemplateException{
    	StringWriter writer = new StringWriter(); 
		Configuration cfg = null;
		freemarker.template.Template template = null ;
		String retValue = templet ;
		if(templet!=null && templet.length()>0){
			cfg = new Configuration();
			cfg.setClassicCompatible(true);
			TempletLoader loader = new TempletLoader(templet) ;
			cfg.setTemplateLoader(loader);   
			cfg.setDefaultEncoding("UTF-8");  
			template = cfg.getTemplate("");
			template.process(values, writer);  
			retValue = writer.toString() ;
		}
		return  retValue;
    }
    
    /**
	 * 发送邮件
	 * @param email
	 * @param cc
	 * @param subject
	 * @param content
	 * @throws Exception
	 */
	public static void sendMail(String email , String cc , String subject , String content ,List<String> filenames) throws Exception{
		SystemConfig config = UKTools.getSystemConfig() ;
		if(config!=null && config.isEnablemail() && config.getEmailid()!=null) {
			SystemMessage systemMessage = UKDataContext.getContext().getBean(SystemMessageRepository.class).findByIdAndOrgi(config.getEmailid(),config.getOrgi()) ;
			MailSender sender = new MailSender(systemMessage.getSmtpserver(),systemMessage.getMailfrom(),systemMessage.getSmtpuser(), decryption(systemMessage.getSmtppassword()),systemMessage.getSeclev(),systemMessage.getSslport());
			if(email!=null){
				sender.send(email,cc, subject, content,filenames);
			}
		}
	}
	
	public static String encode(Object obj) {
		Base64 base64 = new Base64();
    	try {
			return base64.encodeToString(UKTools.toBytes(obj)) ;
		} catch (Exception e) {
			e.printStackTrace();
		}
    	return null;
	}
	@SuppressWarnings("unchecked")
	public static <T> T decode(String str,Class<T> clazz) {
		Base64 base64 = new Base64();
    	try {
			return (T)UKTools.toObject(base64.decode(str)) ;
		} catch (Exception e) {
			e.printStackTrace();
		}
    	return null;
	}
	public static String processContentEncode(String str) throws Exception{
		return Base64.encodeBase64String(str.getBytes("UTF-8")).replaceAll("\\+", "-");
	}
	public static String processContentDecode(String str) throws Exception{
		return new String(Base64.decodeBase64(str.replaceAll("-", "\\+").getBytes()) , "UTF-8");
	}
	
	/**
	 * 
	 * @param defaultFormatValue
	 * @param text
	 * @return
	 */
	public static String processParam(String defaultFormatValue, String text){
		String formatValue = "yyyy-MM-dd" ;
		if(text.matches("[ ]{0,}([Yy]{1,})[ ]{0,}[+-]{0,1}([\\d]{0,})")){
			formatValue = "yyyy" ;
		}else if(text.matches("[ ]{0,}([Mm]{1,})[ ]{0,}[+-]{0,1}([\\d]{0,})")){
			formatValue = "yyyy-MM" ;
		}
		
		return getDays(text, defaultFormatValue!=null && defaultFormatValue.length()>0 ? defaultFormatValue : formatValue) ;
	}
	/***
	 * 计算T+1
	 * @param text
	 * @param format
	 * @return
	 */
	public static String getDays(String text , String format){
		String retDateFormat = text ;
		Pattern pattern = Pattern.compile("[ ]{0,}([TtMmYy]{1,})[ ]{0,}[+-]{0,1}([\\d]{0,})") ;
    	Matcher matcher = pattern.matcher(text) ;
    	if(matcher.find() && matcher.groupCount()>=1){
    		try {
    			if(matcher.group(1) .equalsIgnoreCase("T")){
    				retDateFormat = formatDateValue(format, getDaysParam(text)) ;
    			}else if(matcher.group(1) .equalsIgnoreCase("M")){
    				retDateFormat = formatMonthValue(format, getDaysParam(text)) ;
    			}else if(matcher.group(1) .equalsIgnoreCase("Y")){
    				retDateFormat = String.valueOf((int)Double.parseDouble(String.valueOf(getDaysParam(text))));
    			}
			} catch (ParseException e) {
				e.printStackTrace();
			}
    	}
    	return retDateFormat ;
	}
	
	/***
	 * 计算T+1
	 * @param text
	 * @param format
	 * @return
	 */
	public static Object getDaysParam(String text){
		Map<String,Object>  context = new HashMap<String,Object>();
		context.put("T", processDays()) ;
		context.put("t", processDays()) ;
		context.put("M", processMonth()) ;
		context.put("m", processMonth()) ;
		context.put("Y", processYear()) ;
		context.put("y", processYear()) ;
		
    	return AviatorEvaluator.execute(text , context) ;
	}
	/**
	 * 
	 * @param defaultParam
	 * @param value
	 * @return
	 * @throws ParseException 
	 * @throws Exception 
	 */
	public static String formatDateValue(String format , Object value) throws ParseException{
		if(value!=null && value.toString().matches("[\\d.]{5,}")){
			value = new SimpleDateFormat(format).format(new Date((long)(Double.parseDouble(value.toString())*24*60*60*1000))) ;
		}
		return value!=null ? value.toString() : "0" ;
	}
	/**
	 * 
	 * @param defaultParam
	 * @param value
	 * @return
	 * @throws ParseException 
	 * @throws Exception 
	 */
	public static String formatMonthValue(String formatValue , Object value) throws ParseException{
		if(value!=null && value.toString().matches("[\\d.]{3,}")){
			int months = (int)Double.parseDouble(String.valueOf(value));
			int year = 0 ;
			int month = 0 ;
			if(months%12==0){
				year = months/12 - 1 ;
				month = 12 ;
			}else{
				year = months/12 ;
				month = months % 12 ;
			}
			if(month<10){
				value = String.valueOf(year)+"0"+String.valueOf(month) ;
			}else{
				value = String.valueOf(year)+ String.valueOf(month) ;
			}
			value = new SimpleDateFormat(formatValue).format(new SimpleDateFormat("yyyyMM").parse(String.valueOf(value)));
		}
		return value!=null ? value.toString() : "0" ;
	}
	/**
	 * 
	 * @return
	 */
	public static double processDays(){
		return UKTools.getLastDay(0).getTime()*1.0d/(1000*60*60*24);
	}
	
	/**
	 * 
	 * @return
	 */
	public static double processMonth(){
		Calendar calendar = Calendar.getInstance() ;
		int month = calendar.get(Calendar.YEAR)*12 + calendar.get(Calendar.MONTH )+1 ;
		return month;
	}
	
	/**
	 * 
	 * @return
	 */
	public static double processYear(){
		return  Calendar.getInstance() .get(Calendar.YEAR);
	}
	
	private static final ObjectMapper JSON = new ObjectMapper();
    static {
        JSON.setSerializationInclusion(Include.NON_NULL);
        JSON.configure(SerializationFeature.INDENT_OUTPUT, Boolean.TRUE);
    }

    public static String toJson(Object obj) {
        try {
            return JSON.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return null;
    }
	public static <T> T toObject(String obj,Class<T> clazz) {
		try {
			return JSON.readValue(obj,clazz);
		}  catch (IOException e) {
			e.printStackTrace();
		}

		return null;
	}
    /**
     * 
     * @param message
     */
    public static AsrResult parseAsrResult(String id,String message , int speakms) {
    	AsrResult asrResult = null ;
    	Pattern pattern = Pattern.compile("([\\d]{1,})[\\.]{1}([\\s\\S]*);");
    	Matcher matcher = pattern.matcher(message);    	
    	if(matcher.find() && matcher.groupCount() == 2) {
    		asrResult = new AsrResult(id , matcher.group(2) , matcher.group(1));
    		if(asrResult.getMessage().endsWith("。")) {
    			asrResult.setMessage(asrResult.getMessage().substring(0 , asrResult.getMessage().length() - 1));	
    		}
    	}
    	if(speakms > 0 && asrResult!=null) {
    		asrResult.setSpeakms(speakms);
    	}
    	return asrResult;
    }
    /**
	 * 发送短信
	 * @param email
	 * @param cc
	 * @param subject
	 * @param content
	 * @throws Exception
	 */
	public static boolean sendSmsByTemplate(String phone,String id ,String tpId, Map<String,Object> tplValuesMap , SmsResult result) throws Exception{
		return sendSms(phone, id, UKTools.getSmsTemplate(tpId , result.getOrgi()), UKDataContext.SYSTEM_ORGI , result , tplValuesMap);
	}
	
	/**
	 * 发送短信
	 * @param email
	 * @param cc
	 * @param subject
	 * @param content
	 * @throws Exception
	 */
	public static boolean sendSmsBySmTemplate(String phone,String id ,String tpId, Map<String,Object> tplValuesMap , String orgi) throws Exception{
		return sendSms(phone, id,UKTools.getSmsTemplate(tpId , orgi) , orgi , null , tplValuesMap);
	}
	
	/**
	 * 发送短信
	 * @param email
	 * @param cc
	 * @param subject
	 * @param content
	 * @throws Exception
	 */
	public static boolean sendSms(final String phone,String id , final SmsTemplate tp, String orgi,SmsResult result , Map<String,Object> tplValuesMap) throws Exception{
		SystemConfig config = UKTools.getSystemConfig() ;
		SmsResultRepository smsResultRepository = UKDataContext.getContext().getBean(SmsResultRepository.class);
		if(config!=null) {
			
			
			boolean send = false;
			if(tp != null && tp.isSwitchfrequency() && org.apache.commons.lang3.StringUtils.isNotBlank(tp.getFrequency())){
				Date temp = null;
				final Date end = new Date();
				if("month".equals(tp.getFrequency())){
					temp = getFirstDayDateOfMonth(new Date());//当前月份第一天
				}else if("week".equals(tp.getFrequency())){
					temp = getLastDay(new Date(), 7);
				}else if("day".equals(tp.getFrequency())){
					temp = getStartTime();
				}else if("hour".equals(tp.getFrequency())){
					temp = getLastHour(1);
				}
				
				final Date start = temp;
				
				List<SmsResult> smsResultList = smsResultRepository.findAll(new Specification<SmsResult>(){
					@Override
					public Predicate toPredicate(Root<SmsResult> root, CriteriaQuery<?> query,
							CriteriaBuilder cb) {
						List<Predicate> list = new ArrayList<Predicate>();  
						list.add(cb.equal(root.get("tpid").as(String.class), tp.getId())) ;
						list.add(cb.equal(root.get("phonenumber").as(String.class), phone)) ;
						if(start != null){
							list.add(cb.greaterThan(root.get("createtime").as(Date.class), start)) ;
						}
						if(end != null){
							list.add(cb.lessThan(root.get("createtime").as(Date.class), end)) ;
						}
						Predicate[] p = new Predicate[list.size()];  
						query.where(cb.and(list.toArray(p)));
						query.orderBy(cb.desc(root.get("createtime")));
						return query.getRestriction();
					}});
				
				if(smsResultList != null && smsResultList.size() < tp.getFrequencynum()){
					send = true;
				}
			}else{
				send = true;
			}
			
			if(send){
				
				SystemMessage systemMessage = null;
				if((systemMessage = (SystemMessage) CacheHelper.getSystemCacheBean().getCacheObject(config.getSmsid(), config.getOrgi())) == null) {
					systemMessage = UKDataContext.getContext().getBean(SystemMessageRepository.class).findByIdAndOrgi(!StringUtils.isBlank(config.getSmsid()) ? config.getSmsid() : id,config.getOrgi()) ;
					if(systemMessage!=null) {
						CacheHelper.getSystemCacheBean().put(config.getSmsid(),systemMessage, config.getOrgi()) ;
					}
				}
				if(systemMessage==null) {
					return false;
				}
				if(result == null) {
					result = new SmsResult() ;
				}
				result.setPhonenumber(phone);
				result.setServerid(systemMessage.getId());
				if(StringUtils.isBlank(result.getName())) {
					result.setName(phone);
				}
				result.setCreatetime(new Date());
				//阿里大于
				result.setTpid(tp.getId());//短信模板ID
				result.setTemplettype(tp.getTemplettype());
				if(!StringUtils.isBlank(systemMessage.getSmstype())) {
					/**
					 * 阿里短信：dysms  , httpsms（提供 HTTP POST / GET 方式的 短信网关）
					 */
					result.setSmstype(systemMessage.getSmstype());
					SmsService smsService = (SmsService) UKDataContext.getContext().getBean(systemMessage.getSmstype());
					if(smsService!=null) {
						smsService.send(systemMessage , result , phone , tp , tplValuesMap) ;
						smsResultRepository.save(result) ;
					}
				} 
			}
		}
		return false;
	}

	/**
	 * 
	 * @param userid
	 * @param client
	 * @param session
	 * @param orgi
	 * @param ipaddr
	 * @param hostname
	 * @return
	 */
	public static WorkSession createWorkSession(String userid , String client, String session ,String orgi , String ipaddr , String hostname , String admin , boolean first) {
		WorkSession workSession = new WorkSession();
		workSession.setCreatetime(new Date());
		workSession.setBegintime(new Date());
		workSession.setAgent(userid);
		workSession.setAgentno(userid);
		workSession.setAgentno(userid);
		if(!StringUtils.isBlank(admin) && admin.equalsIgnoreCase("true")) {
			workSession.setAdmin(true);
		}
		
		workSession.setFirsttime(first);
		
		workSession.setIpaddr(ipaddr);
		workSession.setHostname(hostname);
		workSession.setUserid(userid);
		workSession.setClientid(client); 
		workSession.setSessionid(session);
		workSession.setOrgi(orgi);
		
		workSession.setDatestr(UKTools.simpleDateFormat.format(new Date()));
		
		return workSession ;
	} 
	
	/**
	 * 
	 * @param plan
	 * @return
	 */
    public static String convertCrond(JobTask plan){
		StringBuffer strb = new StringBuffer() ;
		String hour = plan.getRepeatJustTime()!=null && plan.getRepeatJustTime() > 0 ? "-" + (plan.getRunBeginHour() + plan.getRepeatJustTime()):"" ;
		if(plan.getRepeatJustTime()!=null && plan.getRepeatJustTime() > 0 && plan.getRunBeginHour() + plan.getRepeatJustTime() > 23) {
			hour = "-23,0-" + ((plan.getRunBeginHour() + plan.getRepeatJustTime() - 23 ) < 23 ? plan.getRunBeginHour() + plan.getRepeatJustTime() - 23 : 23) ;
		}
		if("day".equals(plan.getRunCycle())){
			strb.append(plan.getRunBeginSecond()).append(" ").append(plan.getRunBeginMinute()).append(plan.getIsRepeat() && plan.getRepeatSpace()!=null && plan.getRepeatSpace()<60 ? "/"+ plan.getRepeatSpace() : "").append(" ").append(plan.getRunBeginHour()).append(plan.getIsRepeat() && plan.getRepeatSpace()!=null && plan.getRepeatSpace()>60 ? "/"+ plan.getRepeatSpace()/60 : (hour)).append(" ").append("*").append(plan.getRunSpace() != null && plan.getRunSpace()>0 ? "/"+plan.getRunSpace():"").append(" ").append(" * ?") ;
		}
		if("week".equals(plan.getRunCycle())){
			strb.append(plan.getRunBeginSecond()).append(" ").append(plan.getRunBeginMinute()).append(plan.getIsRepeat() && plan.getRepeatSpace()!=null && plan.getRepeatSpace()<60 ? "/"+ plan.getRepeatSpace() : "").append(" ").append(plan.getRunBeginHour()).append(plan.getIsRepeat() && plan.getRepeatSpace()!=null && plan.getRepeatSpace()>60 ? "/"+ plan.getRepeatSpace()/60 : (hour)).append(" ").append(plan.getRunDates()==null || plan.getRunDates().length==0 ? "*":"?").append(" * ").append(plan.getRunDates()==null || plan.getRunDates().length==0? "?" : StringUtils.join(plan.getRunDates() , ",")).append(plan.getRunSpace()!=null && plan.getRunSpace()>0 ? "/"+plan.getRunSpace(): "") ;
		}
		if("month".equals(plan.getRunCycle())){
			strb.append(plan.getRunBeginSecond()).append(" ").append(plan.getRunBeginMinute()).append(plan.getIsRepeat() && plan.getRepeatSpace()!=null && plan.getRepeatSpace()<60 ? "/"+ plan.getRepeatSpace() : "").append(" ").append(plan.getRunBeginHour()).append(plan.getIsRepeat() && plan.getRepeatSpace()!=null && plan.getRepeatSpace()>60 ? "/"+ plan.getRepeatSpace()/60 : (hour)).append(" ").append(plan.getRunBeginDate()).append(" ").append(plan.getRunDates()==null || plan.getRunDates().length==0? "*" : StringUtils.join(plan.getRunDates() , ",")).append(" ").append(" ?") ;
		}
		return strb.toString() ;
	}
    
    public static Date updateTaskNextFireTime(JobDetail jobDetail) throws Exception{
		Date nextFireDate = new Date();
		Date date = new Date();
		if(jobDetail!=null && jobDetail.getCronexp()!=null && jobDetail.getCronexp().length()>0){
			try {
				nextFireDate = (CronTools.getFinalFireTime(jobDetail.getCronexp(), jobDetail.getNextfiretime()!=null ? jobDetail.getNextfiretime() : date)) ;
			} catch (ParseException e) {
				nextFireDate = new Date(System.currentTimeMillis() + 1000*60*60*24) ; 	//一旦任务的 Cron表达式错误，将下次执行时间自动设置为一天后，避免出现任务永远无法终止的情况
				e.printStackTrace();
			}
		}
		return nextFireDate ;
	}
    /**
     * 
     * @param dialNum
     * @param distype
     * @return
     */
    public static String processSecField(String dialNum , String distype) {
    	StringBuilder strb = new StringBuilder(dialNum) ;
    	if(!StringUtils.isBlank(distype)) {
			if(distype.equals("01")) {
				if(strb.length() > 4) {
					strb.replace(strb.length()/2 - 2, strb.length()/2 + 2, "****") ;
				}else {
					strb.replace(0, strb.length(), "****") ;
				}
			}else if(distype.equals("02")) {
				if(strb.length() > 4) {
					strb.replace(strb.length()-4 , strb.length(), "****") ;
				}else {
					strb.replace(0, strb.length(), "****") ;
				}
			}else if(distype.equals("03")) {
				if(strb.length() > 4) {
					strb.replace(0 , 4, "****") ;
				}else {
					strb.replace(0, strb.length(), "****") ;
				}
			}else if(distype.equals("04")) {
				int length = strb.length() ;
				strb.setLength(0);
				for(int i=0 ; i<length ; i++) {
					strb.append("*") ;
				}
			}else if(distype.equals("00")) {
	//			strb.append(dialNum) ;
			}
    	}
		return strb.toString();
    }
    
    /**
	 * AI配置
	 * @param orgi
	 * @return
	 */
	public static AiConfig initAiConfig(String aiid,String orgi){
		AiConfig aiConfig = (AiConfig) CacheHelper.getSystemCacheBean().getCacheObject(UKDataContext.SYSTEM_CACHE_AI_CONFIG+"_"+aiid, orgi);
		if(UKDataContext.getContext() != null && aiConfig == null){
			AiConfigRepository aiConfigRepository = UKDataContext.getContext().getBean(AiConfigRepository.class) ;
			List<AiConfig> aiConfigList = aiConfigRepository.findByAiidAndOrgi(aiid,orgi) ;
			if(aiConfigList.size() == 0){
				aiConfig = new AiConfig() ;
				aiConfig.setAiid(aiid);
			}else{
				aiConfig = aiConfigList.get(0) ;
				CacheHelper.getSystemCacheBean().put(UKDataContext.SYSTEM_CACHE_AI_CONFIG+"_"+aiConfig.getAiid(),aiConfig, orgi) ;
			}
		}
		return aiConfig ;
	}
	
	public static boolean getDateFormat(HttpServletRequest request){
		boolean convertSuccess = false;
		
		if(request.getParameter("convalue").matches("[\\d]{4}[-]{1}[\\d]{1,2}[-]{1}[\\d]{1,2} [\\d]{1,2}:[\\d]{1,2}:[\\d]{1,2}")){
			convertSuccess = true ;
		}
		return convertSuccess;
		
	}
	public static boolean getDateFormatTemp(HttpServletRequest request){
		boolean convertSuccess = false;
		if(request.getParameter("convalue").matches("[\\d]{4}[-]{1}[\\d]{1,2}[-]{1}[\\d]{1,2}")){
			convertSuccess = true ;
		}
		return convertSuccess;
	}
	
	public static String format(Long time) {
		String formatstr = null ;
		if(time!=null) {
			formatstr = new UCKeFuTime(0, 0, time.intValue()/1000).toString() ; 
		}
		return formatstr ;
	}
	
	public static String format(Integer time) {
		String formatstr = null ;
		if(time!=null) {
			formatstr = new UCKeFuTime(0, 0, time.intValue()).toString() ; 
		}
		return formatstr ;
	}
	
	public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {   
		return OnlineUserUtils.objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);   
	}

	public static JavaType getCollectionType(ObjectMapper mapper, @SuppressWarnings("rawtypes") Class<ArrayList> collectionClass,
			Class<VoiceTranscription> elementClasses) {
		// TODO Auto-generated method stub
		return OnlineUserUtils.objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);   
	}

	

	/**
	 * 选出新的 Master服务器
	 * @param hazelcastInstance
	 */
	public static void voteMaster(HazelcastInstance hazelcastInstance) {
		Set<Member> members = hazelcastInstance.getCluster().getMembers() ;
    	Member master = null ;
    	for(Member member : members) {
    		if(master == null || (member!=null && member.getLongAttribute("start")!=null && member.getLongAttribute("start") < master.getLongAttribute("start"))) {
    			master = member ;
    		}
    	}
    	if(master!=null) {
    		hazelcastInstance.getTopic(UKDataContext.UCKeFuTopic.TOPIC_VOTE.toString()).publish(new RPCDataBean(master.getStringAttribute("id"), master.getAddress().getHost(), master.getAddress().getPort() , master.getLongAttribute("start")));
    	}
	}
	
	/**
	 * 打包语音文件到压缩文件
	 * @param inputFile
	 * @param zipFilename
	 * @throws IOException
	 */
	public static void packageVoiceRecordFile(File voiceFile , ZipOutputStream zipOutputStream) throws IOException {
		if(voiceFile!=null && voiceFile.exists()) {
	        FileInputStream input = new FileInputStream(voiceFile) ;
	        try {    
	        	zipOutputStream.putNextEntry(new ZipEntry(new StringBuffer().append(voiceFile.getName()).toString()));   
	        	int len = 0 ;
	        	byte[] data = new byte[1024] ;
	        	while((len = input.read(data)) > 0) {
	        		zipOutputStream.write(data , 0 , len);
	        	}
	        } catch (IOException e) {    
	            e.printStackTrace();  
	        } finally {    
	            if(input!=null) {
	            	input.close();
	            }
	        }
		}
	}
	
	
	 /**
	 * 质检配置
	 * @param orgi
	 * @return
	 */
	public static QualityConfig initQualityConfig(String orgi){
		QualityConfig qcConfig = (QualityConfig) CacheHelper.getSystemCacheBean().getCacheObject(UKDataContext.SYSTEM_CACHE_QUALITY_CONFIG, orgi);
		if(UKDataContext.getContext() != null && qcConfig == null){
			QualityConfigRepository qcConfigRepository = UKDataContext.getContext().getBean(QualityConfigRepository.class) ;
			List<QualityConfig> qualityConList = qcConfigRepository.findByOrgi(orgi);
			if(qualityConList.size() == 0){
				qcConfig = new QualityConfig() ;
				qcConfig.setOrgi(orgi);
				qcConfig.setCreatetime(new Date());
				qcConfig.setArchivetime(UKDataContext.QUALITY_ARCHIVE_DEFAULT_DAY);
				qcConfig.setAplarchivetime(UKDataContext.QUALITY_ARCHIVE_DEFAULT_DAY);
				qcConfigRepository.save(qcConfig);
			}else{
				qcConfig = qualityConList.get(0) ;
			}
			CacheHelper.getSystemCacheBean().put(UKDataContext.SYSTEM_CACHE_QUALITY_CONFIG,qcConfig, orgi) ;
		}
		return qcConfig ;
	}
	/**
	 * 读取语音文件
	 * @param statusEvent
	 * @throws IOException 
	 */
	@SuppressWarnings({"deprecation", "unchecked" })
	public static File crawlVoiceRecord(StatusEvent statusEvent) throws IOException {
		File tempFile = null ;
		if(!StringUtils.isBlank(statusEvent.getRecordfile())) {
			String fileName = statusEvent.getRecordfile().substring(statusEvent.getRecordfile().lastIndexOf("/"), statusEvent.getRecordfile().length()) ;
			PbxHost pbxHost = CallCenterUtils.pbxhost(statusEvent.getIpaddr()) ;		//根据 PbxHost配置的 方式获取 录音文件的读取方式
			
			if(pbxHost!=null && !StringUtils.isBlank(pbxHost.getDevice())) {
				
				if(!StringUtils.isBlank(pbxHost.getDevice()) && pbxHost.getDevice().equals("phone")) {
					tempFile = new File(System.getProperty("java.io.tmpdir"),statusEvent.getDiscalled()+ fileName.substring(fileName.lastIndexOf("."))) ;
				}else if(!StringUtils.isBlank(pbxHost.getDevice()) && pbxHost.getDevice().equals("extphone")) {
					tempFile = new File(System.getProperty("java.io.tmpdir"),UKTools.callCenterDateFormate.format(statusEvent.getCreatetime())+"_"+statusEvent.getDiscalled()+ fileName.substring(fileName.lastIndexOf("."))) ;
				}else if(!StringUtils.isBlank(pbxHost.getDevice()) && (pbxHost.getDevice().equals("realphone") || pbxHost.getDevice().equals("extrealphone"))) {
					String priphone = statusEvent.getPriphone() ;
					if(StringUtils.isBlank(priphone)) {
						CallOutNamesRepository callOutNamesRepository = UKDataContext.getContext().getBean(CallOutNamesRepository.class) ;
						CallOutNames callOutNames = callOutNamesRepository.findByIdAndOrgi(statusEvent.getNameid(), statusEvent.getOrgi()) ;
						if(callOutNames!=null) {
							priphone = callOutNames.getPriphonenumber() ;
						}else {
							priphone = statusEvent.getDiscalled() ;
						}
					}
					
					if(!StringUtils.isBlank(pbxHost.getDevice()) && pbxHost.getDevice().equals("realphone")) {
						tempFile = new File(System.getProperty("java.io.tmpdir"),priphone+ fileName.substring(fileName.lastIndexOf("."))) ;
					}else if(!StringUtils.isBlank(pbxHost.getDevice()) && pbxHost.getDevice().equals("extrealphone")) {
						
						tempFile = new File(System.getProperty("java.io.tmpdir"),UKTools.callCenterDateFormate.format(statusEvent.getCreatetime())+"_"+priphone+ fileName.substring(fileName.lastIndexOf("."))) ;
					}
				}else {
					tempFile = new File(System.getProperty("java.io.tmpdir"),statusEvent.getId()+ fileName.substring(fileName.lastIndexOf("."))) ;
				}
			}else {
				tempFile = new File(System.getProperty("java.io.tmpdir"),statusEvent.getId()+ fileName.substring(fileName.lastIndexOf("."))) ;
			}
			
			FileOutputStream voiceFileOutputStream = new FileOutputStream(tempFile) ;
			if(pbxHost!=null && !StringUtils.isBlank(pbxHost.getRecordpath())){
				
				URL url = new URL(pbxHost.getRecordpath()+fileName);
				HttpURLConnection conn = null ;
		        try {
		            conn = (HttpURLConnection) url.openConnection();
		            /**
		             * 链接最大超时时间5秒，读取文件最大超时时间不超过60秒
		             */
		            conn.setConnectTimeout(5000);  
		            conn.setReadTimeout(60000);  
		            
		            InputStream inStream = conn.getInputStream();
		            byte[] buffer = new byte[1204];
		            int byteread = 0;
	
		            while ((byteread = inStream.read(buffer)) > 0) {
		            	voiceFileOutputStream.write(buffer, 0, byteread);
		            }
		        } catch (Exception e) {
		            e.printStackTrace();
		        } finally {
		        	voiceFileOutputStream.close();
		        }
			}else{
				
				if("1".equals(statusEvent.getOssstatus())){
					
					SystemConfig systemConfig = (SystemConfig) CacheHelper.getSystemCacheBean().getCacheObject("systemConfig", UKDataContext.SYSTEM_ORGI) ;
					if(systemConfig != null && StringUtils.isNotBlank(systemConfig.getAppid())) {
						String appId = systemConfig.getAppid();
						Map<String,Object> paramsMap = new HashMap<>();
						paramsMap.put("appId",appId);
						paramsMap.put("objectName",statusEvent.getRecordfilename());
						String res = HttpClientUtil.doPost(systemConfig.getCloudservergetossobjecturl(),paramsMap);

						if(StringUtils.isNotBlank(res)){
							Map<String,Object> resultMap = UKTools.toObject(res,HashMap.class);
							if(resultMap != null){
								Boolean success = (Boolean)resultMap.get("success");
								String url = (String)resultMap.get("resultObj");
								if(success != null && success && StringUtils.isNotBlank(url)){
									PoolingHttpClientConnectionManager connMgr;
                                        RequestConfig requestConfig;
                                        final int MAX_TIMEOUT = 300000;
                                        // 设置连接池
                                        connMgr = new PoolingHttpClientConnectionManager();
                                        // 设置连接池大小
                                        connMgr.setMaxTotal(100);
                                        connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal());

                                        RequestConfig.Builder configBuilder = RequestConfig.custom();
                                        // 设置连接超时
                                        configBuilder.setConnectTimeout(MAX_TIMEOUT);
                                        // 设置读取超时
                                        configBuilder.setSocketTimeout(MAX_TIMEOUT);
                                        // 设置从连接池获取连接实例的超时
                                        configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT);
                                        // 在提交请求之前 测试连接是否可用
                                        configBuilder.setStaleConnectionCheckEnabled(true);
                                        requestConfig = configBuilder.build();

                                        CloseableHttpClient httpclient = HttpClients.createDefault();
                                        try {
                                            HttpGet httpPost = new HttpGet(url);
                                            httpPost.setConfig(requestConfig);
                                            HttpResponse httpRes = httpclient.execute(httpPost);

                                            HttpEntity entity = httpRes.getEntity();
                                            if (entity != null) {
                                                InputStream result = entity.getContent();
                                                try{
                                                    byte[] data = new byte[1024];
                                                    int len = 0;
                                                    while((len = result.read(data) ) != -1){
														voiceFileOutputStream.write(data , 0 , len);
                                                    }
                                                } catch (IOException e) {
                                                    e.printStackTrace();
                                                } finally{
                                                    if(voiceFileOutputStream != null){
                                                        try {
															voiceFileOutputStream.close();
                                                        } catch (IOException e) {
                                                            e.printStackTrace();
                                                        }
                                                    }

                                                }
                                            }
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                        }finally {
                                            if(httpclient!=null) {
                                                httpclient.close();
                                            }
                                        }
								}
							}
						}
					}
				}else if(pbxHost!=null && !StringUtils.isBlank(pbxHost.getDevice()) && (pbxHost.getDevice().equals("phone") || pbxHost.getDevice().equals("extphone") || pbxHost.getDevice().equals("realphone") || pbxHost.getDevice().equals("extrealphone"))){
					
					File voiceFile = new File(statusEvent.getRecordfile()) ;
					if(voiceFile.exists() && pbxHost!=null){
						FileInputStream input = new FileInputStream(voiceFile) ;
						try{
							byte[] data = new byte[1024];
							int len = 0;
							while((len = input.read(data) )> 0){
								voiceFileOutputStream.write(data , 0 , len);
							}

						}finally{
							input.close();
							voiceFileOutputStream.close();
						}
					}
				}else{
					
					File voiceFile = new File(statusEvent.getRecordfile()) ;
					tempFile = voiceFile;
					if(voiceFile.exists() && pbxHost!=null){
						FileInputStream input = new FileInputStream(voiceFile) ;
						try{
							byte[] data = new byte[1024];
							int len = 0;
							while((len = input.read(data) )> 0){
								voiceFileOutputStream.write(data , 0 , len);
							}

						}finally{
							input.close();
							voiceFileOutputStream.close();
						}
					}
				}

			}
		}
		return tempFile ;
	}
	
	/**
	 * 计算短信模板表达式
	 * @param param
	 * @param reportList
	 * @return
	 */
	public static String processTempletValue(String smstemplet , Map<String,Object> data){
		StringBuffer strb = new StringBuffer();
		Pattern pattern = Pattern.compile("(\\[[\\S\\s]*?\\])") ;
		Matcher matcher = pattern.matcher(smstemplet) ;
		 while(matcher.find()) {
			 String param = matcher.group(1) ;
			 Object value = data.get(param.substring(1, param.length() - 1)) ;
			 if(value == null) {
				 value = ""  ;
			 }
			 matcher.appendReplacement(strb,value.toString());
		    }
		    matcher.appendTail(strb) ;
		    if(strb.length() == 0){
		    	strb.append(smstemplet) ;
		    }
		
		return strb.toString() ;
	}
	
	/**
	 * 发送邮件 - 群发
	 * @param emails
	 * @param subject
	 * @param content
	 * @param emailid
	 * @param orgi
	 * @throws Exception
	 */
	public static void sendMassMail(List<String> emails ,String subject , String content ,String emailid ,String orgi) throws Exception{
		SystemMessage systemMessage = null;
		if((systemMessage = (SystemMessage) CacheHelper.getSystemCacheBean().getCacheObject(emailid, orgi)) == null) {
			systemMessage = UKDataContext.getContext().getBean(SystemMessageRepository.class).findByIdAndOrgi(emailid,orgi) ;
		}
		if (systemMessage != null) {
			MailSender sender = new MailSender(systemMessage.getSmtpserver(),systemMessage.getMailfrom(),systemMessage.getSmtpuser(), decryption(systemMessage.getSmtppassword()),systemMessage.getSeclev(),systemMessage.getSslport());
			if(emails != null && emails.size()>0){
				sender.send(emails,subject, content);
			}
		}
	}
	
	public static List<CrmScheme> getCrmSchemeList(){
		CrmSchemeRepository CrmSchemeRes = UKDataContext.getContext().getBean(CrmSchemeRepository.class) ;
		List<CrmScheme>  schemeList= CrmSchemeRes.findByOrgi(UKDataContext.SYSTEM_ORGI) ;
		return schemeList;
	}


	/**
	 * 过滤掉超过3个字节的UTF8字符
	 * @param text
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String filterOffUtf8Mb4(String text) throws UnsupportedEncodingException {
		if(text==null){
			return "";
		}
		byte[] bytes = text.getBytes("utf-8");
		ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
		int i = 0;
		while (i < bytes.length) {
			short b = bytes[i];
			if (b > 0) {
				buffer.put(bytes[i++]);
				continue;
			}


			b += 256; // 去掉符号位


			if (((b >> 5) ^ 0x6) == 0) {//高位第三位为0 "110x xxxx"; 字符占用两个字节
				buffer.put(bytes, i, 2);
				i += 2;
			} else if (((b >> 4) ^ 0xE) == 0) {//高四位为0 "1110 xxxx" 字符占用三个字节，
				buffer.put(bytes, i, 3);
				i += 3;
			} else if (((b >> 3) ^ 0x1E) == 0) {//低一位为0 "1111 0xxx" 该情况为emoji表情字符 该字符占用四个字节，
				//buffer.put(starts,0,1);
				i += 4;//跳过之后的4个字节（该四个字节与本自己构成了一个字符，所以跳过）
			} else if (((b >> 2) ^ 0x3E) == 0) {//低二位为0 "1111 10xx" 该字符占用五个字节
				//buffer.put(starts,0,1);
				i += 5;
			} else if (((b >> 1) ^ 0x7E) == 0) {//低三位为0 "1111 110x" 占用六个字节
				//buffer.put(starts,0,1);
				i += 6;
			} else {
				buffer.put(bytes[i++]);
			}
		}
		buffer.flip();
		return new String(buffer.array(), "utf-8");
	}
	/**
	 * 获取ID
	 * @param userid
	 * @param appid
	 * @param orgi
	 * @return
	 */
	public static String getUniKey(String userid, String appid ,String orgi) {
		return userid ;
	}
	
	/**
	 * 格式化时长
	 * @param start
	 * @param end
	 * @return
	 */
	public static String getDuration(long start , long end) {
		Interval interval = new Interval(start , end);
		Period p = interval.toPeriod();
		int hour = 0;
		if(p.getDays() > 0){
			hour = p.getDays()*24 + p.getHours();
		}else{
			hour = p.getHours();
		}
		String duration = new StringBuffer().append(UKTools.defaultNumberFormt.format(hour)).append(":").append(UKTools.defaultNumberFormt.format(p.getMinutes())).append(":").append(UKTools.defaultNumberFormt.format(p.getSeconds())).toString() ;
		return duration;
	}
	
	/**
	 * 获取小时数
	 * @return
	 */
	public static int getHour() {
		return Calendar.getInstance().get(Calendar.HOUR_OF_DAY) ;
	}
	
	/**
	 * 获取分钟数
	 * @return
	 */
	public static int getMinute() {
		return Calendar.getInstance().get(Calendar.MINUTE) ;
	}
	
	/**
	 * 判断是否需要转储
	 * @return
	 */
	public static boolean needRunDump() {
		SystemConfig systemConfig = UKTools.getSystemConfig() ;
		int startsec = systemConfig.getDumpstarthour() * 3600 + systemConfig.getDumpstartmin()*60 ;
		int endsec = systemConfig.getDumpendhour() * 3600 + systemConfig.getDumpendmin()*60 ;
		int current = UKTools.getHour() * 3600 + UKTools.getMinute() * 60 ;
		boolean run = false ;
		if(startsec > endsec) {
			if(current >= startsec || current < endsec) {
				run = true ;
			}
		}else if(current >= startsec && current < endsec){
			run = true ;
		}
		return run && systemConfig.isDumpcall();
	}
	
	/**
	 * 播放录音方法
	 * @param response
	 * @param callid
	 * @param orgi
	 * @param history
	 * @param isEnabletneant
	 * @throws IOException
	 */
	@SuppressWarnings("unchecked")
	public static void playVoice(HttpServletResponse response ,final String callid,final String orgi,final boolean history,boolean isEnabletneant) throws IOException{
		if (!StringUtils.isBlank(callid)) {
			StatusEventRepository statusEventRes = UKDataContext.getContext().getBean(StatusEventRepository.class);
			StatusEventHistoryRepository statusEventHistoryRes = UKDataContext.getContext().getBean(StatusEventHistoryRepository.class);
			PbxHostRepository pbxHostRes = UKDataContext.getContext().getBean(PbxHostRepository.class);
			
			//通话记录字段
			String s_hostid = null;
			String s_recordfile = null;
			String s_ossstatus = null;
			String s_recordfilename = null;
			String s_ipaddr = null;
			String s_orgi = null;
			Object statusEventData = null ;
			//字段赋值
			if (history) {
				StatusEventHistory statusEventHistory = null;
				if (!StringUtils.isBlank(orgi)) {
					statusEventHistory = statusEventHistoryRes.findByIdAndOrgi(callid, orgi);
				}else{
					statusEventHistory = statusEventHistoryRes.findById(callid);
				}
				if (statusEventHistory != null) {
					s_hostid = statusEventHistory.getHostid();
					s_recordfile = statusEventHistory.getRecordfile();
					s_ossstatus = statusEventHistory.getOssstatus();
					s_recordfilename = statusEventHistory.getRecordfilename();
					s_ipaddr = statusEventHistory.getIpaddr();
					s_orgi = statusEventHistory.getOrgi();
				}
				statusEventData = statusEventHistory ;
			}else{
				StatusEvent statusEvent = null;
				if (!StringUtils.isBlank(orgi)) {
					statusEvent = statusEventRes.findByIdAndOrgi(callid, orgi);
				}else{
					statusEvent = statusEventRes.findById(callid);
				}
				if (statusEvent != null) {
					s_hostid = statusEvent.getHostid();
					s_recordfile = statusEvent.getRecordfile();
					s_ossstatus = statusEvent.getOssstatus();
					s_recordfilename = statusEvent.getRecordfilename();
					s_ipaddr = statusEvent.getIpaddr();
					s_orgi = statusEvent.getOrgi();
				}
				statusEventData = statusEvent ;
			}
			
			
			
			if(!StringUtils.isBlank(s_hostid)){
	            PbxHost pbxHost = null;		//根据 PbxHost配置的 方式获取 录音文件的读取方式
	            if(isEnabletneant){
	                pbxHost = pbxHostRes.findById(s_hostid);
	            }else{
	                pbxHost = pbxHostRes.findByIdAndOrgi(s_hostid, s_orgi) ;
	            }
				if(pbxHost != null && !StringUtils.isBlank(pbxHost.getRecordpath()) && pbxHost.getRecordpath() != "" && StringUtils.isNotBlank(s_recordfile)){
					String fileName = s_recordfile ;
					if(s_recordfile.lastIndexOf("/") >= 0) {
						fileName = s_recordfile.substring(s_recordfile.lastIndexOf("/"), s_recordfile.length()) ;
					}else {
						fileName = "/"+fileName ;
					}
					Map<String, Object> values = new HashMap<String , Object>();
					try {
						values.put("data", statusEventData) ;
						response.sendRedirect(UKTools.getTemplet(pbxHost.getRecordpath(), values) + fileName);
					} catch (TemplateException e) {
						e.printStackTrace();
					}
				}else{
					if(s_recordfile != null) {
	                    //在远程oss
					    if("1".equals(s_ossstatus)){
	                        SystemConfig systemConfig = (SystemConfig) CacheHelper.getSystemCacheBean().getCacheObject("systemConfig", UKDataContext.SYSTEM_ORGI) ;
	                        if(systemConfig != null && StringUtils.isNotBlank(systemConfig.getAppid())) {
	                            String appId = systemConfig.getAppid();
	                            Map<String,Object> paramsMap = new HashMap<>();
	                            paramsMap.put("appId",appId);
	                            paramsMap.put("objectName",s_recordfilename);
	                            String res = HttpClientUtil.doPost(systemConfig.getCloudservergetossobjecturl(),paramsMap);

	                            if(StringUtils.isNotBlank(res)){
									Map<String,Object> resultMap = UKTools.toObject(res,HashMap.class);
	                                if(resultMap != null){
	                                    Boolean success = (Boolean)resultMap.get("success");
	                                    String url = (String)resultMap.get("resultObj");
	                                    if(success != null && success && StringUtils.isNotBlank(url)){
	                                        response.sendRedirect(url);
	                                    }
	                                }
	                            }
	                        }
	                    }else{
	                        File voiceFile = new File(s_recordfile) ;
	                        if(voiceFile != null && voiceFile.exists()){
	                            response.setHeader("Accept-Ranges","bytes");
	                            response.setContentType("audio/mp3");
	                            response.setHeader("Content-Length",String.valueOf(voiceFile.length()));
	                            response.setContentLength((int) voiceFile.length());
	                            FileInputStream input = new FileInputStream(voiceFile) ;
	                            try{
	                                byte[] data = new byte[1024];
	                                int len = 0;
	                                while((len = input.read(data) )> 0){
	                                    response.getOutputStream().write(data , 0 , len);
	                                }
	                            }finally{
	                                input.close();
	                            }
	                        }else {
	                        	response.setHeader("Accept-Ranges","bytes");
	                        	response.setContentType("audio/mp3");
	                        	HttpURLConnection conn = null ;
	                        	InputStream inputStream = null ;
	                        	try {

	                        		String fileName = s_recordfile ;
	                        		if(s_recordfile.lastIndexOf("/") >= 0) {
	                        			fileName = s_recordfile.substring(s_recordfile.lastIndexOf("/"), s_recordfile.length()) ;
	                        		}else {
	                        			fileName = "/"+fileName ;
	                        		}

	                        		URL serverUrl = new URL("http://"+s_ipaddr+"/"+fileName);  
	                        		conn = (HttpURLConnection) serverUrl.openConnection();
	                        		if(conn!=null) {
		                        		conn.setRequestMethod("GET");  
		                        		conn.setConnectTimeout(3*1000);
		                        		Map<String,List<String>> header = conn.getHeaderFields() ;
		                        		if(header!=null && header.size() > 0) {
		                        			Iterator<String> iterator = header.keySet().iterator() ;
		                        			while(iterator.hasNext()) {
		                        				String key = iterator.next() ;
		                        				if(header.get(key)!=null && header.get(key).size() > 0) {
		                        					response.setHeader(key, header.get(key).get(0));
		                        				}
		                        			}
		                        		}
		                        		//得到输入流
		                        		inputStream = conn.getInputStream();
		                        		if(inputStream!=null) {
			                        		byte[] data = new byte[1024] ;
			                        		int length = 0 ;
			                        		while((length = inputStream.read(data)) > 0) {
			                        			response.getOutputStream().write(data , 0 , length);
			                        		}
		                        		}
	                        		}
	                        	}finally {
	                        		if(conn!=null) {
	                        			conn.disconnect();
	                        		}
	                        		if(inputStream!=null) {
	                        			inputStream.close();
	                        		}
	                        	}
	                        }
	                    }
					}else {
						response.setContentType("text/html");
						response.getOutputStream().write(s_hostid.getBytes());
					}
				}
			}
		}
	}
	
	/**
	 * 传入时间的当月第一天日期
	 * @param date
	 * @return
	 */
	public static Date getFirstDayDateOfMonth(final Date date) {
		
		final Calendar cal = Calendar.getInstance();
		
		cal.setTime(date);
		
		final int last = cal.getActualMinimum(Calendar.DAY_OF_MONTH);
		
		cal.set(Calendar.DAY_OF_MONTH, last);
		
		return cal.getTime();
		
	}
	
    /**
     * 获取距离当前时间 n个小时之前的时间点
     * @param hour
     * @return
     */
	public static Date getLastHour(int hour){
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) - hour);
		return cal.getTime();
	}
	
	/**
     * @param hour
   * @return
   */
	public static String getTimeHourMin(Date date){
		StringBuffer strb = new StringBuffer() ;
		if(date!=null) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(date);
			int hour = cal.get(Calendar.HOUR_OF_DAY) ;
	
			if(cal.get(Calendar.MINUTE) >= 30) {
				strb.append(String.format("%02d", hour)).append(":30").append("~").append(String.format("%02d", hour+1)).append(":00");
			}else {
				strb.append(String.format("%02d", hour)).append(":00").append("~").append(String.format("%02d", hour)).append(":30");
			}
		}
		return strb.toString();
	}
	
	 /**
   * @param hour
 * @return
 */
	public static String getTimeHour(Date date){
		StringBuffer strb = new StringBuffer() ;
		if(date!=null) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(date);
			int hour = cal.get(Calendar.HOUR_OF_DAY) ;
			strb.append(String.format("%02d", hour)).append(":00").append("~").append(String.format("%02d", hour+1)).append(":00");
		}
		return strb.toString();
	}
	
	
	/**
	 * 发送短信
	 * @param email
	 * @param cc
	 * @param subject
	 * @param content
	 * @throws Exception
	 */
	public static SmsResult sendSmsRep(String phone,String id ,String template  , SmsResult result) throws Exception{
		SystemConfig config = UKTools.getSystemConfig() ;
		SmsResultRepository smsResultRepository = UKDataContext.getContext().getBean(SmsResultRepository.class);
		if(config!=null) {
			SystemMessage systemMessage = null;
			if((systemMessage = (SystemMessage) CacheHelper.getSystemCacheBean().getCacheObject(id, config.getOrgi())) == null) {
				systemMessage = UKDataContext.getContext().getBean(SystemMessageRepository.class).findByIdAndOrgi(!StringUtils.isBlank(config.getSmsid()) ? config.getSmsid() : id,config.getOrgi()) ;
			}
			if(result == null) {
				result = new SmsResult() ;
				result.setSendok(false);
			}
			if(systemMessage==null) {
				result.setSendok(false);
				return result;
			}
			result.setPhonenumber(phone);
			if(StringUtils.isBlank(result.getName())) {
				result.setName(phone);
			}
			SysDic sysDic= UKeFuDic.getInstance().getDicItem(systemMessage.getSmstype());
			//阿里大于
			result.setSmstext(template);
			if(sysDic!=null && "dysms".equals(sysDic.getCode())) {
				//设置超时时间-可自行调整
				result.setSmstype(sysDic.getCode());
				System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
				System.setProperty("sun.net.client.defaultReadTimeout", "10000");
				//初始化ascClient需要的几个参数
				final String domain = "dysmsapi.aliyuncs.com";//短信API产品域名（接口地址固定，无需修改）
				//替换成你的AK
				final String accessKeyId = systemMessage.getAppkey();//你的accessKeyId,参考本文档步骤2
				final String accessKeySecret = systemMessage.getAppsec();//你的accessKeySecret，参考本文档步骤2
				result.setAppkey(accessKeyId);
				result.setSubtime(new Date());
				//初始化ascClient,暂时不支持多region（请勿修改）
				IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId,accessKeySecret);
				IAcsClient acsClient = new DefaultAcsClient(profile);
				 //组装请求对象
				CommonRequest request = new CommonRequest();
				 
		        request.setVersion("2017-05-25");
		        request.setAction("SendSms");
				request.setDomain(domain);
				 //使用post提交
				 request.setMethod(MethodType.POST);
				 request.putQueryParameter("RegionId", "cn-hangzhou");
				 //必填:待发送手机号。支持以逗号分隔的形式进行批量调用，批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
				 request.putQueryParameter("PhoneNumbers",phone);
				 //必填:短信签名-可在短信控制台中找到
				 request.putQueryParameter("SignName",systemMessage.getSign());
				 //必填:短信模板-可在短信控制台中找到
				 request.putQueryParameter("TemplateCode", systemMessage.getTpcode());
				 //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
				 //友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
				 if(!StringUtils.isBlank(template)) {
					 request.putQueryParameter("TemplateParam",template);
				 }
				 //可选-上行短信扩展码(扩展码字段控制在7位或以下，无特殊需求用户请忽略此字段)
				 //request.setSmsUpExtendCode("90997");
				 //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
				 request.putQueryParameter("OutId","yourOutId");
				//请求失败这里会抛ClientException异常
				 try {
					 CommonResponse sendSmsResponse = acsClient.getCommonResponse(request);
					if(sendSmsResponse.getData() != null && sendSmsResponse.getData().equals("OK")) {
						result.setSendresult(sendSmsResponse.getData());
						result.setSendok(true);
					}else if(!StringUtils.isBlank(sendSmsResponse.getData())){
						result.setSendresult(sendSmsResponse.getData());
					}
				 }catch(Exception ex) {
					 result.setSendresult(ex.getMessage());
					 throw ex;
				 }finally {
					 result.setSendtime(new Date());
					 smsResultRepository.save(result) ;
				 }
			}
		}
		return result;
	}
}
